package com.pet_service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pet_service.config.RedisConstant;
import com.pet_service.entity.User;
import com.pet_service.exception.BusinessException;
import com.pet_service.result.ResultCodeEnum;
import com.pet_service.service.LoginService;
import com.pet_service.service.UserService;
import com.pet_service.sms.IHuYiSMSUtil;
import com.pet_service.util.JwtUtil;
import com.pet_service.vo.LoginVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 邹全伸
 * @version 1.0
 * @date 2025-10-05 14:40
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private IHuYiSMSUtil iHuYiSMSUtil;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    @Override
    public void getSMSCode(String phone) {
        //1. 检查手机号码是否为空
        if (!StringUtils.hasText(phone)) {
            throw new BusinessException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }

        //2. 检查Redis中是否已经存在该手机号码的key
        String key = RedisConstant.APP_LOGIN_PREFIX + phone;
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            //若存在，则检查其存在的时间
            Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
            if (RedisConstant.APP_LOGIN_CODE_TTL_SEC - expire < RedisConstant.APP_LOGIN_CODE_RESEND_TIME_SEC) {
                //若存在时间不足一分钟，响应发送过于频繁
                throw new BusinessException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
            }
        }

        //3.发送短信，并将验证码存入Redis
        String verifyCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        System.out.println("验证码：" + verifyCode);
        //先用假接口测试
        String result = iHuYiSMSUtil.testSendCode(phone, verifyCode);
        System.out.println("短信发送结果 = " + result);
        //把手机号码和验证码存入Redis
        redisTemplate.opsForValue().set(key, verifyCode, RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);
    }

    @Override
    public String login(LoginVo loginVo) {
        //1.判断手机号码和验证码是否为空
        if (!StringUtils.hasText(loginVo.getPhone())) {
            throw new BusinessException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }

        log.info("查询手机号：{}", loginVo.getPhone());

        //2.判断验证码是否为空
        if (!StringUtils.hasText(loginVo.getCode())) {
            throw new BusinessException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
        }

        //3.判断用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", loginVo.getPhone());
        User user = userService.getOne(queryWrapper);
        if(user == null){
            //用户不存在
            throw new BusinessException(ResultCodeEnum.APP_LOGIN_USER_NOT_EXIST);
        }

        //4.验证码校验
        String key = RedisConstant.APP_LOGIN_PREFIX + loginVo.getPhone();
        //从Redis中获取验证码
        String code = (String) redisTemplate.opsForValue().get(key);
        System.out.println("code = " + code);
        if (code == null) {
            throw new BusinessException(ResultCodeEnum.APP_LOGIN_CODE_EXPIRED);
        }

        //5.比较输入验证和Redis中的验证码
        if (!code.equals(loginVo.getCode())) {
            //验证码错误
            throw new BusinessException(ResultCodeEnum.APP_LOGIN_CODE_ERROR);
        }

        //6.判断用户是否被禁用
        if (user.getStatus().equals(0)) {
            throw new BusinessException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);
        }

        //7.创建并返回TOKEN
        Map<String, String> claims = new HashMap<>();
        //用户id
        claims.put("id", user.getId().toString());
        //用户名称
        claims.put("username", user.getUsername());
        //用户手机号码
        claims.put("phone", loginVo.getPhone());
        String token = JwtUtil.generateToken("mySecret", "pet_service", "userAuth", claims);
        return token;
    }
}
